﻿using System;
using System.Collections.Generic;
using System.Linq;
using Autodesk.Revit.DB;
using Autodesk.Revit.DB.Mechanical;
using Autodesk.Revit.UI.Selection;
using YArchitech.Controls;
using YArchitech.Revit;

namespace YArchitech.HVAC
{
	public class AlignmentDucts
	{
		public AlignmentDucts()
		{
		}

		public AlignmentDucts(Autodesk.Revit.DB.Document document, Selection selection)
		{
			this.doc = document;
			this.sel = selection;
		}

		public void AlignDuctSet(string alignmentType, bool beUser, double offset, int nSelStype)
		{
			new HYDuctAlignment();
			Duct duct = null;
			Duct duct2 = null;
			List<Duct> list = new List<Duct>();
			XYZ globalPoint = null;
			Outline outline = null;
			if (nSelStype == 2 && alignmentType != "Reference")
			{
				KeyValuePair<Outline, List<Duct>> crossDucts = this.GetCrossDucts();
				outline = crossDucts.Key;
				list = crossDucts.Value;
				if (outline == null || list == null)
				{
					return;
				}
				list = this.GetStartDuct(list);
				if (list.Count < 1)
				{
					return;
				}
			}
			if (beUser)
			{
				if (alignmentType == "Top")
				{
					if (nSelStype == 2)
					{
						using (List<Duct>.Enumerator enumerator = list.GetEnumerator())
						{
							while (enumerator.MoveNext())
							{
								duct2 = enumerator.Current;
								globalPoint = this.OutSidePoint(outline, duct2);
								this.AlignBranchDucts(duct2, globalPoint, 1, offset, outline);
							}
							return;
						}
					}
					this.SelectDuctAlignDucts(ref duct, ref duct2, ref globalPoint, true);
					this.AlignBranchDucts(duct, globalPoint, 1, offset, null);
					return;
				}
				if (alignmentType == "Middle")
				{
					if (nSelStype == 2)
					{
						using (List<Duct>.Enumerator enumerator = list.GetEnumerator())
						{
							while (enumerator.MoveNext())
							{
								duct2 = enumerator.Current;
								globalPoint = this.OutSidePoint(outline, duct2);
								this.AlignBranchDucts(duct2, globalPoint, 2, offset, outline);
							}
							return;
						}
					}
					this.SelectDuctAlignDucts(ref duct, ref duct2, ref globalPoint, true);
					this.AlignBranchDucts(duct, globalPoint, 2, offset, null);
					return;
				}
				if (!(alignmentType == "Bottom"))
				{
					return;
				}
				if (nSelStype == 2)
				{
					using (List<Duct>.Enumerator enumerator = list.GetEnumerator())
					{
						while (enumerator.MoveNext())
						{
							duct2 = enumerator.Current;
							globalPoint = this.OutSidePoint(outline, duct2);
							this.AlignBranchDucts(duct2, globalPoint, 3, offset, outline);
						}
						return;
					}
				}
				this.SelectDuctAlignDucts(ref duct, ref duct2, ref globalPoint, true);
				this.AlignBranchDucts(duct, globalPoint, 3, offset, null);
				return;
			}
			else
			{
				if (alignmentType == "Top")
				{
					if (nSelStype == 2)
					{
						using (List<Duct>.Enumerator enumerator = list.GetEnumerator())
						{
							while (enumerator.MoveNext())
							{
								Duct duct3 = enumerator.Current;
								duct2 = duct3;
								offset = this.GetDuctOffset(duct3, 1);
								globalPoint = this.OutSidePoint(outline, duct2);
								this.AlignBranchDucts(duct2, globalPoint, 1, offset, outline);
							}
							return;
						}
					}
					this.SelectDuctAlignDucts(ref duct, ref duct2, ref globalPoint, false);
					offset = this.GetDuctOffset(duct, 1);
					this.AlignBranchDucts(duct2, globalPoint, 1, offset, outline);
					return;
				}
				if (alignmentType == "Middle")
				{
					if (nSelStype == 2)
					{
						using (List<Duct>.Enumerator enumerator = list.GetEnumerator())
						{
							while (enumerator.MoveNext())
							{
								Duct duct4 = enumerator.Current;
								duct2 = duct4;
								offset = this.GetDuctOffset(duct4, 2);
								globalPoint = this.OutSidePoint(outline, duct2);
								this.AlignBranchDucts(duct2, globalPoint, 2, offset, outline);
							}
							return;
						}
					}
					this.SelectDuctAlignDucts(ref duct, ref duct2, ref globalPoint, false);
					offset = this.GetDuctOffset(duct, 2);
					this.AlignBranchDucts(duct2, globalPoint, 2, offset, null);
					return;
				}
				if (alignmentType == "Bottom")
				{
					if (nSelStype == 2)
					{
						using (List<Duct>.Enumerator enumerator = list.GetEnumerator())
						{
							while (enumerator.MoveNext())
							{
								Duct duct5 = enumerator.Current;
								duct2 = duct5;
								offset = this.GetDuctOffset(duct5, 3);
								globalPoint = this.OutSidePoint(outline, duct2);
								this.AlignBranchDucts(duct2, globalPoint, 3, offset, outline);
							}
							return;
						}
					}
					this.SelectDuctAlignDucts(ref duct, ref duct2, ref globalPoint, false);
					offset = this.GetDuctOffset(duct, 3);
					this.AlignBranchDucts(duct2, globalPoint, 3, offset, null);
					return;
				}
				if (!(alignmentType == "Reference"))
				{
					return;
				}
				YJKLine baseLine = null;
				XYZ pickPoint = null;
				this.SelectAlignSideDucts(ref baseLine, ref duct2, ref globalPoint, ref pickPoint);
				this.AlignBranchDuctsToLine(duct2, pickPoint, baseLine);
			}
		}

		private List<Duct> GetStartDuct(List<Duct> olDuctList)
		{
			List<Duct> list = new List<Duct>();
			List<string> list2 = new List<string>();
			foreach (Duct duct in olDuctList)
			{
				string item = duct.GetParameter(BuiltInParameter.RBS_SYSTEM_NAME_PARAM).AsString();
				if (!list2.Contains(item))
				{
					list.Add(duct);
					list2.Add(item);
				}
			}
			return list;
		}

		private XYZ OutSidePoint(Outline oline, Duct d)
		{
			XYZ result;
			try
			{
				YJKPiping<Duct> hypiping = new YJKPiping<Duct>(d);
				if (oline.Contains(hypiping.StartConnector.Origin, 1E-07) && !oline.Contains(hypiping.EndConnector.Origin, 1E-07))
				{
					result = hypiping.EndConnector.Origin;
				}
				else if (!oline.Contains(hypiping.StartConnector.Origin, 1E-07))
				{
					oline.Contains(hypiping.EndConnector.Origin, 1E-07);
					result = hypiping.StartConnector.Origin;
				}
				else
				{
					result = hypiping.StartConnector.Origin;
				}
			}
			catch
			{
				result = null;
			}
			return result;
		}

		private KeyValuePair<Outline, List<Duct>> GetCrossDucts()
		{
			List<Duct> list = new List<Duct>();
			KeyValuePair<Outline, List<Duct>> result;
			try
			{
				double viewProjectElevation = this.GetViewProjectElevation(this.doc.ActiveView);
				double levelToUpLevelHeight = this.GetLevelToUpLevelHeight(this.doc, viewProjectElevation);
				PickedBox pickedBox = this.sel.PickBox((Autodesk.Revit.UI.Selection.PickBoxStyle)0, "请选择要调整的风管！");
				double x = pickedBox.Min.X;
				double x2 = pickedBox.Max.X;
				double y = pickedBox.Min.Y;
				double y2 = pickedBox.Max.Y;
				if (pickedBox.Max.X < pickedBox.Min.X)
				{
					x = pickedBox.Max.X;
					x2 = pickedBox.Min.X;
				}
				if (pickedBox.Max.Y < pickedBox.Min.Y)
				{
					y = pickedBox.Max.Y;
					y2 = pickedBox.Min.Y;
				}
				Outline outline = new Outline(new XYZ(x, y, viewProjectElevation), new XYZ(x2, y2, viewProjectElevation + levelToUpLevelHeight));
				BoundingBoxIntersectsFilter boundingBoxIntersectsFilter = new BoundingBoxIntersectsFilter(outline);
				foreach (Element element in new FilteredElementCollector(this.doc).OfClass(typeof(Duct)).OfCategory(BuiltInCategory.OST_DuctCurves).WherePasses(boundingBoxIntersectsFilter).ToElements())
				{
					if (element is Duct && this.IsDuctCross(outline, element as Duct))
					{
						list.Add(element as Duct);
					}
				}
				List<Duct> value = this.OrderByDucts(list);
				result = new KeyValuePair<Outline, List<Duct>>(outline, value);
			}
			catch (Exception ex)
			{
				throw ex;
			}
			return result;
		}

		private List<Duct> OrderByDucts(List<Duct> ductList)
		{
			new List<Duct>();
			ductList.Sort((Duct duct1, Duct duct2) => this.CompareDuct(duct1, duct2));
			return ductList;
		}

		private int CompareDuct(Duct duct1, Duct duct2)
		{
			YJKPiping<Duct> hypiping = new YJKPiping<Duct>(duct1);
			YJKPiping<Duct> hypiping2 = new YJKPiping<Duct>(duct2);
			double weightOrDiameter = hypiping.GetWeightOrDiameter();
			double heightOrDiameter = hypiping.GetHeightOrDiameter();
			double weightOrDiameter2 = hypiping2.GetWeightOrDiameter();
			double heightOrDiameter2 = hypiping2.GetHeightOrDiameter();
			double num = 0.016404199475065617;
			if (weightOrDiameter - weightOrDiameter2 > num)
			{
				return -1;
			}
			if (weightOrDiameter - weightOrDiameter2 < num && heightOrDiameter - heightOrDiameter2 > num)
			{
				return -1;
			}
			return 1;
		}

		private bool IsDuctCross(Outline oLine, Duct d)
		{
			bool result;
			try
			{
				YJKPiping<Duct> hypiping = new YJKPiping<Duct>(d);
				if (oLine.Contains(hypiping.StartConnector.Origin, 1E-07) && !oLine.Contains(hypiping.EndConnector.Origin, 1E-07))
				{
					result = true;
				}
				else if (!oLine.Contains(hypiping.StartConnector.Origin, 1E-07) && oLine.Contains(hypiping.EndConnector.Origin, 1E-07))
				{
					result = true;
				}
				else
				{
					result = false;
				}
			}
			catch
			{
				result = false;
			}
			return result;
		}

		private double GetViewProjectElevation(Autodesk.Revit.DB.View view)
		{
			double result = 0.0;
			Level genLevel = view.GenLevel;
			if (genLevel == null)
			{
				return result;
			}
			return genLevel.ProjectElevation;
		}

		public double GetLevelToUpLevelHeight(Autodesk.Revit.DB.Document doc, double dElevation)
		{
			double num = 26.246719160104988;
			double result;
			try
			{
				PlanViewRange viewRange = (doc.ActiveView as ViewPlan).GetViewRange();
				ElementId levelId = viewRange.GetLevelId(0);
                ElementId levelId2 = viewRange.GetLevelId((PlanViewPlane)1);
				if (levelId2 != null && doc.GetElementById(levelId) != null && doc.GetElementById(levelId2) is Level)
				{
					Level level = doc.GetElementById(levelId2) as Level;
					Level level2 = doc.GetElementById(levelId) as Level;
                    num = level.Elevation + viewRange.GetOffset((PlanViewPlane)1);
					num -= level2.Elevation;
				}
				result = num;
			}
			catch
			{
				result = num;
			}
			return result;
		}

		public static Level GetUpLevelByElevation(Autodesk.Revit.DB.Document doc, double dElevation)
		{
			Level result = null;
			List<Level> list = new FilteredElementCollector(doc).OfClass(typeof(Level)).Cast<Level>().ToList<Level>();
			SortedDictionary<double, Level> sortedDictionary = new SortedDictionary<double, Level>();
			foreach (Level level in list)
			{
				if (level.Elevation > dElevation)
				{
					double key = Math.Abs(level.Elevation - dElevation);
					if (!sortedDictionary.ContainsKey(key))
					{
						sortedDictionary.Add(key, level);
					}
				}
			}
			if (sortedDictionary.Count > 0)
			{
				result = sortedDictionary.First<KeyValuePair<double, Level>>().Value;
			}
			return result;
		}

		private void SelectDuctAlignDucts(ref Duct baseDuct, ref Duct startDuct, ref XYZ globalPoint, bool beUser = false)
		{
			ISelectionFilter selectionFilter = new NRDuctFilter();
			string text = "选择基准风管……";
			if (beUser)
			{
				text = "选择对齐风管……";
			}
			Reference reference = this.sel.PickObject((Autodesk.Revit.UI.Selection.ObjectType)1, selectionFilter, text);
			globalPoint = reference.GlobalPoint;
			baseDuct = (this.doc.GetElementByRef(reference) as Duct);
			if (!beUser)
			{
				text = "选择对齐风管……";
				reference = this.sel.PickObject((Autodesk.Revit.UI.Selection.ObjectType)1, selectionFilter, text);
				globalPoint = reference.GlobalPoint;
				startDuct = (this.doc.GetElementByRef(reference) as Duct);
			}
		}

		private bool SelectAlignSideDucts(ref YJKLine hyLine, ref Duct baseDuct, ref XYZ globalPoint, ref XYZ pickPoint)
		{
			Reference reference = this.sel.PickObject((Autodesk.Revit.UI.Selection.ObjectType)3, "请选择一条风管的边线为基准参考线……");
			XYZ globalPoint2 = reference.GlobalPoint;
			Duct duct;
			for (duct = (this.doc.GetElementByRef(reference) as Duct); duct == null; duct = (this.doc.GetElementByRef(reference) as Duct))
			{
				reference = this.sel.PickObject((Autodesk.Revit.UI.Selection.ObjectType)3, "请重新选择风管上的边线为基准参考线……");
				globalPoint2 = reference.GlobalPoint;
			}
			hyLine = this.GetDuctSelectEdgeLine(duct, globalPoint2);
			globalPoint = globalPoint2;
			Reference reference2 = this.sel.PickObject((Autodesk.Revit.UI.Selection.ObjectType)2, "选择风管的一边进行对齐……");
			pickPoint = reference2.GlobalPoint;
			for (baseDuct = (this.doc.GetElementByRef(reference2) as Duct); baseDuct == null; baseDuct = (this.doc.GetElementByRef(reference2) as Duct))
			{
				reference2 = this.sel.PickObject((Autodesk.Revit.UI.Selection.ObjectType)2, "选择风管的一边进行对齐……");
				pickPoint = reference2.GlobalPoint;
			}
			YJKLine ductSelectEdgeLine = this.GetDuctSelectEdgeLine(baseDuct, pickPoint);
			if (hyLine.IsParallel(ductSelectEdgeLine.Line))
			{
				return true;
			}
			YJKMessageBox.Information("两条边线必须平行，才能进行边线对齐操作！");
			return false;
		}

		private YJKLine GetDuctSelectEdgeLine(Duct duct, XYZ pickPoint)
		{
			YJKPiping<Duct> hypiping = new YJKPiping<Duct>(duct);
			XYZ xyz = hypiping.StartConnector.Origin.Subtract(hypiping.EndConnector.Origin).Normalize();
			return new YJKLine(pickPoint, pickPoint.Add(xyz));
		}

		private double GetDuctOffset(Duct duct, int alignTypeNum)
		{
			YJKPiping<Duct> hypiping = new YJKPiping<Duct>(duct);
			double result = 0.0;
			switch (alignTypeNum)
			{
			case 1:
				result = hypiping.GetHeightOrDiameter() / 2.0 + duct.LevelOffset;
				break;
			case 2:
				result = duct.LevelOffset;
				break;
			case 3:
				result = duct.LevelOffset - hypiping.GetHeightOrDiameter() / 2.0;
				break;
			}
			return result;
		}

		public bool AlignBranchDucts(Duct startDuct, XYZ globalPoint, int alignTypeNum, double alignOffset, Outline oLine = null)
		{
			Document document = startDuct.Document;
			List<Connector> connectorAll = YJKRevitTools.GetConnectorAll(startDuct);
			Connector connector = (connectorAll[0].Origin.DistanceTo(globalPoint) > connectorAll[1].Origin.DistanceTo(globalPoint)) ? connectorAll[1] : connectorAll[0];
			ElementNode rootNode = new ElementNode(startDuct, connector);
			string text = "";
			List<ElementNode> list = new List<ElementNode>();
			this.SearchFittingNodes(rootNode, ref list, false);
			if (list == null || list.Count == 0)
			{
				this.AlignNotConnedDucts(alignOffset, new List<Duct>
				{
					startDuct
				}, alignTypeNum, ref text);
			}
			else
			{
				FamilySymbol originalElbow = this.GetOriginalElbow(list);
				foreach (ElementNode elementNode in list)
				{
					Element element = elementNode.Element;
					XYZ point = (element.Location as LocationPoint).Point;
					if (oLine == null || oLine.Contains(point, 1E-07))
					{
						List<Duct> fittingConnedDucts = this.GetFittingConnedDucts(element);
						int count = fittingConnedDucts.Count;
						if (count >= 1)
						{
							if (count < 2)
							{
								this.AlignNotConnedDucts(alignOffset, fittingConnedDucts, alignTypeNum, ref text);
							}
							else
							{
								string fittingName = this.GetFittingName(elementNode);
								this.DeleteElementConnectorFiting(element);
								List<XYZ> ductsConnectorOrigin = this.GetDuctsConnectorOrigin(fittingConnedDucts, point);
								this.AlignNotConnedDucts(alignOffset, fittingConnedDucts, alignTypeNum, ref text);
								this.ReConnDucts(fittingConnedDucts, ductsConnectorOrigin, point, elementNode, originalElbow, fittingName);
								this.doc.Regenerate();
							}
						}
					}
				}
			}
			return true;
		}

		private FamilySymbol GetOriginalElbow(List<ElementNode> listFittingNodes)
		{
			FamilySymbol result = null;
			foreach (ElementNode elementNode in listFittingNodes)
			{
				FamilyInstance familyInstance = elementNode.Element as FamilyInstance;
                if ((int)(familyInstance.MEPModel as MechanicalFitting).PartType == 5)
				{
					result = familyInstance.Symbol;
					break;
				}
			}
			return result;
		}

		public bool AlignBranchDuctsToLine(Duct startDuct, XYZ pickPoint, YJKLine baseLine)
		{
			Document document = startDuct.Document;
			List<Connector> connectorAll = YJKRevitTools.GetConnectorAll(startDuct);
			Connector connector = (connectorAll[0].Origin.DistanceTo(pickPoint) > connectorAll[1].Origin.DistanceTo(pickPoint)) ? connectorAll[1] : connectorAll[0];
			ElementNode rootNode = new ElementNode(startDuct, connector);
			string text = "";
			List<ElementNode> list = new List<ElementNode>();
			this.SearchFittingNodes(rootNode, ref list, false);
			if (list == null || list.Count == 0)
			{
				this.AlignDuctToEdge(startDuct, pickPoint, baseLine, ref text);
			}
			else
			{
				FamilySymbol originalElbow = this.GetOriginalElbow(list);
				YJKPiping<Duct> hypiping = new YJKPiping<Duct>(startDuct);
				XYZ start = YJKRevitTools.SetZToZero(hypiping.StartConnector.Origin);
				XYZ end = YJKRevitTools.SetZToZero(hypiping.EndConnector.Origin);
				pickPoint = YJKRevitTools.SetZToZero(pickPoint);
				YJKLine hyline = new YJKLine(start, end);
				hyline.MakeUnBound();
				XYZ project = hyline.GetProject(pickPoint);
				XYZ vector = pickPoint.Subtract(project).Normalize();
				foreach (ElementNode elementNode in list)
				{
					Element element = elementNode.Element;
					XYZ point = (element.Location as LocationPoint).Point;
					List<Duct> fittingConnedDucts = this.GetFittingConnedDucts(element);
					int count = fittingConnedDucts.Count;
					string fittingName = this.GetFittingName(elementNode);
					this.DeleteElementConnectorFiting(element);
					List<XYZ> ductsConnectorOrigin = this.GetDuctsConnectorOrigin(fittingConnedDucts, point);
					this.AlignDuctsToEdge(baseLine, fittingConnedDucts, vector, ref text);
					this.ReConnDucts(fittingConnedDucts, ductsConnectorOrigin, point, elementNode, originalElbow, fittingName);
				}
			}
			return true;
		}

		private bool AlignDuctsToEdge(YJKLine baseLine, List<Duct> listDuct, XYZ vector, ref string alignMSG)
		{
			Document document = listDuct[0].Document;
			foreach (Duct duct in listDuct)
			{
				YJKPiping<Duct> hypiping = new YJKPiping<Duct>(duct);
				XYZ xyz = YJKRevitTools.SetZToZero(hypiping.StartConnector.Origin);
				XYZ xyz2 = YJKRevitTools.SetZToZero(hypiping.EndConnector.Origin);
				YJKLine hyline = new YJKLine(xyz, xyz2);
				if (hyline.IsParallel(baseLine.Line) || hyline.IsLineOnLine(baseLine.Line))
				{
					XYZ xyz3 = xyz.Add(xyz2) / 2.0;
					double num = hypiping.GetWeightOrDiameter() / 2.0;
					XYZ pickPoint = xyz3.Add(num * vector);
					this.AlignDuctToEdge(duct, pickPoint, baseLine, ref alignMSG);
					document.Regenerate();
				}
			}
			return true;
		}

		private bool AlignDuctToEdge(Duct startDuct, XYZ pickPoint, YJKLine baseLine, ref string alignMSG)
		{
			SubTransaction subTransaction = null;
			bool result;
			try
			{
				Document document = startDuct.Document;
				YJKPiping<Duct> hypiping = new YJKPiping<Duct>(startDuct);
				XYZ origin = hypiping.StartConnector.Origin;
				XYZ origin2 = hypiping.EndConnector.Origin;
				YJKLine hyline = new YJKLine(origin, origin2);
				if (!hyline.IsParallel(baseLine.Line) && !hyline.IsLineOnLine(baseLine.Line))
				{
					alignMSG = "风管与基准边线不平行，不能进行对齐操作！";
					result = false;
				}
				else
				{
					subTransaction = new SubTransaction(document);
					subTransaction.Start();
					XYZ xyz = origin.Subtract(origin2).Normalize();
					YJKLine hyline2 = new YJKLine(pickPoint, pickPoint.Add(xyz));
					double xydistance = hyline2.GetXYDistance(baseLine.Line);
					XYZ xyz2 = baseLine.GetXYVector(hyline2.Line).Normalize();
					result = (hypiping.Piping.Location as LocationCurve).Move(xydistance * xyz2);
				}
			}
			catch (Exception ex)
			{
				alignMSG = ex.Message;
				result = false;
			}
			finally
			{
				if (subTransaction != null)
				{
					TransactionStatus status = subTransaction.GetStatus();
					if ((int)status == 1)
					{
						subTransaction.Commit();
					}
					else if ((int)status == 5)
					{
						subTransaction.RollBack();
					}
				}
			}
			return result;
		}

		private void ReConnDucts(List<Duct> ductList, List<XYZ> pointList, XYZ fiPoint, ElementNode fiNode, FamilySymbol fsElbow, string familyName)
		{
			switch (ductList.Count)
			{
			case 2:
				this.ConnTwoDucts(ductList, fiPoint, fsElbow);
				return;
			case 3:
				this.ConnThreeDucts(ductList, pointList, fiNode, familyName);
				return;
			case 4:
				this.ConnFourDucts(ductList, pointList, fiNode, familyName);
				return;
			default:
				return;
			}
		}

		private void ConnThreeDucts(List<Duct> ductList, List<XYZ> pointList, ElementNode fiNode, string familyName)
		{
			int num = this.CheckDuctShape(ductList);
			if (num != 1 && num != 2)
			{
				return;
			}
			int num2 = -1;
			List<YJKPiping<Duct>> hyDucts = this.OrderThreeDucts(ductList, pointList, fiNode, ref num2);
			List<Duct> list = null;
			List<XYZ> xyzs = null;
			this.GetDuctAndPointList(hyDucts, ref list, ref xyzs);
			List<string> listName = new List<string>();
			HYDuctConnect hyductConnect = new HYDuctConnect();
			string text = "";
			ConnectDuctManage connectDuctManage = new ConnectDuctManage();
			ConnectDuctStyle connDuctStyle = connectDuctManage.GetConnDuctStyle(familyName);
			if (num != 1)
			{
				if (num != 2)
				{
					return;
				}
				switch (num2)
				{
				case 1:
					if (connDuctStyle == ConnectDuctStyle.RightAngleTee || connDuctStyle == ConnectDuctStyle.IntubationTee)
					{
						listName = connectDuctManage.GetConnFittingNames(connDuctStyle);
					}
					else
					{
						listName = connectDuctManage.GetConnFittingNames(ConnectDuctStyle.RoundAngleTee);
					}
					hyductConnect.IsConnecteddByRoundAngleTee(list, xyzs, listName, ref text);
					return;
				case 2:
					if (connDuctStyle == ConnectDuctStyle.TShapeTee)
					{
						listName = connectDuctManage.GetConnFittingNames(connDuctStyle);
					}
					else
					{
						listName = connectDuctManage.GetConnFittingNames(ConnectDuctStyle.YShapeTee);
					}
					hyductConnect.IsConnecteddByYShapeTee(list, xyzs, listName, ref text);
					return;
				case 3:
				{
					ConnectDuctStyle connStyle = ConnectDuctStyle.CommonTee;
					listName = connectDuctManage.GetFittingNames(connStyle);
					hyductConnect.NewTeeFittingY(list, xyzs, listName, ref text);
					return;
				}
				default:
					return;
				}
			}
			else
			{
				switch (num2)
				{
				case 1:
				{
					ConnectDuctStyle connStyle = ConnectDuctStyle.RightAngleTeeRound;
					listName = connectDuctManage.GetFittingNames(connStyle);
					hyductConnect.NewTeeFittingT(list, xyzs, listName, ref text);
					return;
				}
				case 2:
				{
					ConnectDuctStyle connStyle = ConnectDuctStyle.RightAngleTeeRound;
					listName = connectDuctManage.GetFittingNames(connStyle);
					hyductConnect.IsConnecteddByYShapeTee(new List<Duct>
					{
						list[1],
						list[2],
						list[0]
					}, xyzs, listName, ref text);
					return;
				}
				case 3:
				{
					ConnectDuctStyle connStyle = ConnectDuctStyle.CommonTeeRound;
					listName = connectDuctManage.GetFittingNames(connStyle);
					hyductConnect.NewTeeFittingY(list, xyzs, listName, ref text);
					return;
				}
				default:
					return;
				}
			}
		}

		private string GetFittingName(ElementNode fiNode)
		{
			return (fiNode.Element as FamilyInstance).Symbol.Family.Name;
		}

		private void ConnFourDucts(List<Duct> ductList, List<XYZ> pointList, ElementNode fiNode, string familyName)
		{
			int num = this.CheckDuctShape(ductList);
			if (num != 1 && num != 2)
			{
				return;
			}
			List<YJKPiping<Duct>> list = this.PreOrderDucts(ductList, pointList, fiNode);
			list = this.OrderFourDucts(list);
			List<Duct> ducts = null;
			List<XYZ> xyzs = null;
			this.GetDuctAndPointList(list, ref ducts, ref xyzs);
			List<string> listName = new List<string>();
			HYDuctConnect hyductConnect = new HYDuctConnect();
			string text = "";
			ConnectDuctManage connectDuctManage = new ConnectDuctManage();
			ConnectDuctStyle connDuctStyle = connectDuctManage.GetConnDuctStyle(familyName);
			if (num == 1)
			{
				ConnectDuctStyle connStyle = ConnectDuctStyle.IntubationCrossRound;
				listName = connectDuctManage.GetFittingNames(connStyle);
				hyductConnect.NewCrossFitting(ducts, xyzs, listName, ref text);
				return;
			}
			if (num != 2)
			{
				return;
			}
			if (connDuctStyle == ConnectDuctStyle.RightAngleCross || connDuctStyle == ConnectDuctStyle.IntubationCross)
			{
				listName = connectDuctManage.GetConnFittingNames(connDuctStyle);
			}
			else
			{
				listName = connectDuctManage.GetConnFittingNames(ConnectDuctStyle.RoundAngleCross);
			}
			hyductConnect.IsConnecteddByCross(ducts, xyzs, listName, ref text);
		}

		private void GetDuctAndPointList(List<YJKPiping<Duct>> hyDucts, ref List<Duct> listDuct, ref List<XYZ> listPoint)
		{
			listDuct = new List<Duct>();
			listPoint = new List<XYZ>();
			foreach (YJKPiping<Duct> hypiping in hyDucts)
			{
				listDuct.Add(hypiping.Piping);
				listPoint.Add(hypiping.GlobalPoint);
			}
		}

		private List<YJKPiping<Duct>> OrderThreeDucts(List<Duct> ductList, List<XYZ> pointList, ElementNode fiNode, ref int connTypeNum)
		{
			if (ductList.Count != 3)
			{
				return null;
			}
			Duct preViewDuctNode = this.GetPreViewDuctNode(fiNode);
			if (preViewDuctNode == null)
			{
				return null;
			}
			YJKPiping<Duct> hypiping = new YJKPiping<Duct>(ductList[0], pointList[0]);
			YJKPiping<Duct> hypiping2 = new YJKPiping<Duct>(ductList[1], pointList[1]);
			YJKPiping<Duct> hypiping3 = new YJKPiping<Duct>(ductList[2], pointList[2]);
			List<YJKPiping<Duct>> result = new List<YJKPiping<Duct>>();
			if (hypiping.Piping.Id.IntegerValue == preViewDuctNode.Id.IntegerValue)
			{
				result = this.ConfirmOtherDuctsOrder(hypiping, hypiping2, hypiping3, ref connTypeNum);
			}
			else if (hypiping2.Piping.Id.IntegerValue == preViewDuctNode.Id.IntegerValue)
			{
				result = this.ConfirmOtherDuctsOrder(hypiping2, hypiping, hypiping3, ref connTypeNum);
			}
			else
			{
				result = this.ConfirmOtherDuctsOrder(hypiping3, hypiping, hypiping2, ref connTypeNum);
			}
			return result;
		}

		private List<YJKPiping<Duct>> PreOrderDucts(List<Duct> ductList, List<XYZ> pointList, ElementNode fiNode)
		{
			List<YJKPiping<Duct>> list = new List<YJKPiping<Duct>>();
			Duct preViewDuctNode = this.GetPreViewDuctNode(fiNode);
			YJKPiping<Duct> hypiping = null;
			for (int i = 0; i < ductList.Count; i++)
			{
				YJKPiping<Duct> hypiping2 = new YJKPiping<Duct>(ductList[i], pointList[i]);
				if (hypiping2.Piping.Id.IntegerValue != preViewDuctNode.Id.IntegerValue)
				{
					list.Add(hypiping2);
				}
				else
				{
					hypiping = hypiping2;
				}
			}
			if (hypiping != null)
			{
				list.Insert(0, hypiping);
			}
			return list;
		}

		private List<YJKPiping<Duct>> OrderFourDucts(List<YJKPiping<Duct>> preOrderDucts)
		{
			if (preOrderDucts == null || preOrderDucts.Count != 4)
			{
				return null;
			}
			List<YJKPiping<Duct>> list = new List<YJKPiping<Duct>>();
			YJKPiping<Duct> hypiping = preOrderDucts[0];
			YJKPiping<Duct> hypiping2 = preOrderDucts[1];
			YJKPiping<Duct> hypiping3 = preOrderDucts[2];
			YJKPiping<Duct> hypiping4 = preOrderDucts[3];
			if (hypiping.IsParallel(hypiping2.Piping) || hypiping.IsPipingOnLine(hypiping2.Piping))
			{
				list = this.FindFirstDucts(hypiping, hypiping2, hypiping3, hypiping4);
			}
			else if (hypiping.IsParallel(hypiping3.Piping) || hypiping.IsPipingOnLine(hypiping3.Piping))
			{
				list = this.FindFirstDucts(hypiping, hypiping3, hypiping2, hypiping4);
			}
			else if (hypiping.IsParallel(hypiping4.Piping) || hypiping.IsPipingOnLine(hypiping4.Piping))
			{
				list = this.FindFirstDucts(hypiping, hypiping4, hypiping2, hypiping3);
			}
			else
			{
				list.Add(hypiping);
				list.Add(hypiping2);
				list.Add(hypiping3);
				list.Add(hypiping4);
			}
			return list;
		}

		private List<YJKPiping<Duct>> FindFirstDucts(YJKPiping<Duct> hyFirstDuct, YJKPiping<Duct> hySecondDuct, YJKPiping<Duct> hyThirdDuct, YJKPiping<Duct> hyFourthDuct)
		{
			List<YJKPiping<Duct>> list = new List<YJKPiping<Duct>>();
			if (hyFirstDuct.GetDuctEQDiameter() < hySecondDuct.GetDuctEQDiameter())
			{
				list.Add(hySecondDuct);
				list.Add(hyFirstDuct);
				list.Add(hyThirdDuct);
				list.Add(hyFourthDuct);
			}
			else
			{
				list.Add(hyFirstDuct);
				list.Add(hySecondDuct);
				list.Add(hyThirdDuct);
				list.Add(hyFourthDuct);
			}
			return list;
		}

		private List<YJKPiping<Duct>> ConfirmOtherDuctsOrder(YJKPiping<Duct> hyFirstDuct, YJKPiping<Duct> hySecondDuct, YJKPiping<Duct> hyThirdDuct, ref int connTypeNum)
		{
			List<YJKPiping<Duct>> list = new List<YJKPiping<Duct>>();
			connTypeNum = -1;
			hyFirstDuct.GetDuctEQDiameter();
			hySecondDuct.GetDuctEQDiameter();
			hyThirdDuct.GetDuctEQDiameter();
			if (hyFirstDuct.IsPipingOnLine(hySecondDuct.Piping) || hyFirstDuct.IsParallel(hySecondDuct.Piping))
			{
				if (!hyFirstDuct.IsVertical(hyThirdDuct.Piping))
				{
					return null;
				}
				list.Add(hyFirstDuct);
				list.Add(hySecondDuct);
				list.Add(hyThirdDuct);
				connTypeNum = 1;
			}
			else if (hyFirstDuct.IsPipingOnLine(hyThirdDuct.Piping) || hyFirstDuct.IsParallel(hyThirdDuct.Piping))
			{
				if (!hyFirstDuct.IsVertical(hySecondDuct.Piping))
				{
					return null;
				}
				list.Add(hyFirstDuct);
				list.Add(hyThirdDuct);
				list.Add(hySecondDuct);
				connTypeNum = 1;
			}
			else if (hyFirstDuct.IsVertical(hyThirdDuct.Piping) && hyFirstDuct.IsVertical(hySecondDuct.Piping))
			{
				list.Add(hyFirstDuct);
				list.Add(hySecondDuct);
				list.Add(hyThirdDuct);
				connTypeNum = 2;
			}
			else
			{
				list.Add(hyFirstDuct);
				list.Add(hySecondDuct);
				list.Add(hyThirdDuct);
				connTypeNum = 3;
			}
			return list;
		}

		private Duct GetPreViewDuctNode(ElementNode fiNode)
		{
			Duct result = null;
			Element element = fiNode.Preview.Element;
			if (element is Duct)
			{
				result = (element as Duct);
			}
			else
			{
				Element element2 = fiNode.Preview.Preview.Element;
				if (element2 is Duct)
				{
					result = (element2 as Duct);
				}
			}
			return result;
		}

		private int CheckDuctShape(List<Duct> ductList)
		{
			if (ductList == null || ductList.Count < 1)
			{
				return -1;
			}
			string connectorSharpName = YJKRevitTools.GetConnectorSharpName(new YJKPiping<Duct>(ductList[0]).StartConnector.Connector);
			if (connectorSharpName != "矩形" && connectorSharpName != "圆形")
			{
				return -1;
			}
			using (List<Duct>.Enumerator enumerator = ductList.GetEnumerator())
			{
				while (enumerator.MoveNext())
				{
					if (YJKRevitTools.GetConnectorSharpName(new YJKPiping<Duct>(enumerator.Current).StartConnector.Connector) != connectorSharpName)
					{
						return -1;
					}
				}
			}
			if (connectorSharpName != "矩形")
			{
				return 1;
			}
			return 2;
		}

		private void ConnTwoDucts(List<Duct> ductList, XYZ fiPoint, FamilySymbol fsElbow)
		{
			if (ductList == null || ductList.Count != 2)
			{
				return;
			}
			Document document = ductList[0].Document;
			YJKPiping<Duct> hypiping = new YJKPiping<Duct>(ductList[0]);
			YJKPiping<Duct> hypiping2 = new YJKPiping<Duct>(ductList[1]);
			Connector closeConnector = hypiping.GetCloseConnector(fiPoint, false);
			Connector closeConnector2 = hypiping2.GetCloseConnector(fiPoint, false);
			if (hypiping.IsParallel(hypiping2.Piping))
			{
				document.Create.NewTransitionFitting(closeConnector, closeConnector2);
				return;
			}
			FamilyInstance familyInstance = document.Create.NewElbowFitting(closeConnector, closeConnector2);
			if (fsElbow != null)
			{
				familyInstance.Symbol = fsElbow;
			}
		}

		private List<XYZ> GetDuctsConnectorOrigin(List<Duct> connedDucts, XYZ basePoint)
		{
			List<XYZ> list = new List<XYZ>();
			foreach (Duct piping in connedDucts)
			{
				YJKPiping<Duct> hypiping = new YJKPiping<Duct>(piping);
				XYZ origin = hypiping.StartConnector.Origin;
				XYZ origin2 = hypiping.EndConnector.Origin;
				double num = origin.DistanceTo(basePoint);
				double num2 = origin2.DistanceTo(basePoint);
				XYZ item = (num > num2) ? origin2 : origin;
				list.Add(item);
			}
			return list;
		}

		private void SearchFittingNodes(ElementNode rootNode, ref List<ElementNode> listFittingNodes, bool beReduce = false)
		{
			new SearchBranch(rootNode).DoSearch();
			this.GetAllElemNode(rootNode, ref listFittingNodes, beReduce);
		}

		private void GetAllElemNode(ElementNode eNode, ref List<ElementNode> listENode, bool beReduce = false)
		{
			int integerValue = eNode.Element.Category.Id.IntegerValue;
			if (eNode == null)
			{
				return;
			}
			if (integerValue == -2008010)
			{
				List<Connector> elementAllConnector = YJKRevitTools.GetElementAllConnector(eNode.Element);
				using (List<Connector>.Enumerator enumerator = elementAllConnector.GetEnumerator())
				{
					while (enumerator.MoveNext())
					{
						if (enumerator.Current.CoordinateSystem.BasisZ.Z > 1E-05)
						{
							return;
						}
					}
				}
				new YJKPipeConnectorHelper();
				int count = elementAllConnector.Count;
				bool flag = true;
				bool flag2 = false;
				if (count == 2 && elementAllConnector.ElementAt(0).IsConnected && elementAllConnector.ElementAt(1).IsConnected)
				{
					XYZ basisZ = elementAllConnector.ElementAt(0).CoordinateSystem.BasisZ;
					XYZ basisZ2 = elementAllConnector.ElementAt(1).CoordinateSystem.BasisZ;
					if (basisZ.IsAlmostEqualTo(basisZ2 * -1.0, 0.0001))
					{
						flag = false;
					}
					if (!flag && YJKRevitTools.GetConnectConnector(elementAllConnector.ElementAt(0)).Owner is Duct && YJKRevitTools.GetConnectConnector(elementAllConnector.ElementAt(1)).Owner is Duct)
					{
						flag2 = true;
					}
					if (flag)
					{
						Duct connectoredDuct = this.GetConnectoredDuct(elementAllConnector.ElementAt(0));
						Duct connectoredDuct2 = this.GetConnectoredDuct(elementAllConnector.ElementAt(1));
						if (connectoredDuct == null || connectoredDuct2 == null || YJKRevitTools.IsRiserDuct(connectoredDuct) || YJKRevitTools.IsRiserDuct(connectoredDuct2))
						{
							flag = false;
						}
					}
				}
				if (beReduce)
				{
					if (flag2)
					{
						listENode.Add(eNode);
					}
				}
				else if (count == 3 || count == 4 || flag || flag2)
				{
					listENode.Add(eNode);
				}
			}
			if (eNode.Next != null)
			{
				this.GetAllElemNode(eNode.Next, ref listENode, beReduce);
			}
			if (eNode.SubElementNode != null)
			{
				foreach (ElementNode eNode2 in eNode.SubElementNode)
				{
					this.GetAllElemNode(eNode2, ref listENode, beReduce);
				}
			}
		}

		private Duct GetConnectoredDuct(Connector connedConn)
		{
			Duct result = null;
			Connector connectConnector = YJKRevitTools.GetConnectConnector(connedConn);
			if (connectConnector == null)
			{
				return null;
			}
			if (connectConnector.Owner is Duct)
			{
				result = (connectConnector.Owner as Duct);
			}
			else
			{
				List<Connector> elementAllConnector = YJKRevitTools.GetElementAllConnector(connectConnector.Owner);
				if (elementAllConnector == null || elementAllConnector.Count != 2)
				{
					return null;
				}
				Connector connectConnector2 = YJKRevitTools.GetConnectConnector((elementAllConnector[0] == connectConnector) ? elementAllConnector[1] : elementAllConnector[0]);
				if (connectConnector2 == null)
				{
					return null;
				}
				Element owner = connectConnector2.Owner;
				if (owner is Duct)
				{
					result = (owner as Duct);
				}
			}
			return result;
		}

		private List<Duct> GetFittingConnedDucts(Element fiElem)
		{
			List<Connector> elementAllConnector = YJKRevitTools.GetElementAllConnector(fiElem);
			List<Duct> list = new List<Duct>();
			foreach (Connector connector in elementAllConnector)
			{
				Connector connectConnector = YJKRevitTools.GetConnectConnector(connector);
				if (connectConnector != null)
				{
					if (connectConnector.Owner is Duct)
					{
						list.Add(connectConnector.Owner as Duct);
					}
					else
					{
						foreach (Connector connector2 in YJKRevitTools.GetElementAllConnector(connectConnector.Owner))
						{
							if (connector2 != connectConnector)
							{
								Connector connectConnector2 = YJKRevitTools.GetConnectConnector(connector2);
								if (connectConnector2 != null)
								{
									Element owner = connectConnector2.Owner;
									if (owner is Duct)
									{
										list.Add(owner as Duct);
									}
								}
							}
						}
					}
				}
			}
			return list;
		}

		private void DeleteElementConnectorFiting(Element elem)
		{
			Document document = elem.Document;
			List<Element> list = new List<Element>();
			list.Add(elem);
			foreach (Connector connector in YJKRevitTools.GetElementAllConnector(elem))
			{
				Connector connectConnector = YJKRevitTools.GetConnectConnector(connector);
				if (connectConnector != null)
				{
					Element owner = connectConnector.Owner;
					if (owner is FamilyInstance && owner.Category.Id.IntegerValue == -2008010)
					{
						list.Add(owner);
					}
				}
			}
			foreach (Element elem2 in list)
			{
				document.DeleteElement(elem2);
			}
		}

		public bool AlignNotConnedDucts(double alignOffset, IList<Duct> ducts, int alignTypeNum, ref string alignMSG)
		{
			SubTransaction subTransaction = null;
			bool result;
			try
			{
				alignMSG = "";
				if (ducts == null || ducts.Count < 1)
				{
					alignMSG = "对齐风管不能为空！";
					result = false;
				}
				else
				{
					Document document = ducts[0].Document;
					YJKPiping<Duct>[] array = new YJKPiping<Duct>[ducts.Count];
					for (int i = 0; i < ducts.Count; i++)
					{
						array[i] = new YJKPiping<Duct>(ducts[i]);
					}
					subTransaction = new SubTransaction(document);
					subTransaction.Start();
					double offSet = 0.0;
					foreach (YJKPiping<Duct> hypiping in array)
					{
						double num = hypiping.GetHeightOrDiameter() / 2.0;
						switch (alignTypeNum)
						{
						case 1:
							offSet = alignOffset - num;
							break;
						case 2:
							offSet = alignOffset;
							break;
						case 3:
							offSet = alignOffset + num;
							break;
						}
						hypiping.SetOffSet(offSet);
					}
					result = true;
				}
			}
			catch (Exception ex)
			{
				alignMSG = ex.Message;
				result = false;
			}
			finally
			{
				if (subTransaction != null)
				{
					TransactionStatus status = subTransaction.GetStatus();
					if ((int)status == 1)
					{
						subTransaction.Commit();
					}
					else if ((int)status == 5)
					{
						subTransaction.RollBack();
					}
				}
			}
			return result;
		}

		private Document doc;

		private Selection sel;
	}
}
